/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package data;

import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.terrain.geomipmap.TerrainQuad;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import pointfinder.AbstractPointContainer;
import pointfinder.GeometryContainer;
import pointfinder.PointEntity;
import pointfinder.TerrainContainer;

/**
 *
 * @author oxplay
 */
public class Grid3d extends AbstractGrid3d {

    private final static Logger logger = Logger.getLogger(Grid3d.class.getName());

    public Grid3d() {
        logger.setLevel(Level.OFF);
    }

    public void examineSpatial(Spatial spatial) {
        if (spatial instanceof TerrainQuad) {
            TerrainQuad terrain = (TerrainQuad) spatial;
            TerrainContainer terrainContainer = new TerrainContainer(terrain);
            containers.add(terrainContainer);
        } else if (spatial instanceof Node) {
            Node findingnode = (Node) spatial;
            for (int i = 0; i < findingnode.getQuantity(); i++) {
                Spatial child = findingnode.getChild(i);
                examineSpatial(child);
            }
        } else if (spatial instanceof Geometry) {
            Geometry geom = (Geometry) spatial;
            GeometryContainer geometryContainer = new GeometryContainer(geom);
            containers.add(geometryContainer);
        }
    }

    public Vector3i getCatchPoint(Vector3i vect, int seekSize) {
        Vector3i retVect = null;
        int distance = -1;
        int tmpStartX = vect.x - seekSize;
        int tmpStartY = vect.y - seekSize;
        int tmpStartZ = vect.z - seekSize;
        int tmpEndX = vect.x + seekSize;
        int tmpEndY = vect.y + seekSize;
        int tmpEndZ = vect.z + seekSize;
        for (int x = tmpStartX; x <= tmpEndX; x++) {
            for (int y = tmpStartY; y <= tmpEndY; y++) {
                for (int z = tmpStartZ; z <= tmpEndZ; z++) {
                    Vector3i actVect = new Vector3i(x, y, z);
                    int actualDistance = Math.abs(x - vect.x) + Math.abs(y - vect.y) + Math.abs(z - vect.z);
                    if (getGridPoint(actVect).equals(PointEntity.MOVEABLE)) {
                        if (distance == -1 || actualDistance < distance) {
                            distance = actualDistance;
                            retVect = actVect;
                        }
                    }
                }
            }
        }
        return retVect;
    }

    public ArrayList<Vector3i> getPointsNearVector(Vector3i vect, int size) {
        ArrayList<Vector3i> vectors = new ArrayList<Vector3i>();
        Vector3i start = new Vector3i(vect.x - size, vect.y - size, vect.z - size);
        Vector3i end = new Vector3i(vect.x + size, vect.y + size, vect.z + size);
        Set<Vector3i> set = getMoveableVectors(start, end);
        for (Iterator<Vector3i> it = set.iterator(); it.hasNext();) {
            Vector3i vector3i = it.next();
            vectors.add(vector3i);
        }
        return vectors;
    }

    @Override
    public Grid3d clone() {
        Grid3d pathFindGrid = new Grid3d();
        pathFindGrid.containers = new ArrayList<AbstractPointContainer>(this.containers);
        return pathFindGrid;
    }

    public PointEntity getGridPoint(Vector3i vect) {
        PointEntity retpoint = PointEntity.NEUTRAL;
        for (Iterator<AbstractPointContainer> it = containers.iterator(); it.hasNext();) {
            AbstractPointContainer abstractPointContainer = it.next();
            PointEntity point = abstractPointContainer.getPoint(vect);
            if(point != null){
                if (point.equals(PointEntity.BLOCKADE)) {
                    return PointEntity.BLOCKADE;
                }
                if (point.equals(PointEntity.MOVEABLE)) {
                    retpoint = PointEntity.MOVEABLE;
                }
            }
        }
        return retpoint;
    }

    public Set<Vector3i> getMoveableVectors(Vector3i from, Vector3i to) {
        Set<Vector3i> allList = new HashSet<Vector3i>();
        for (int x = from.x; x <= to.x; x++) {
            for (int z = from.z; z <= to.z; z++) {
                for (int y = from.y; y <= to.y; y++) {
                    Vector3i actVect = new Vector3i(x, y, z);
                    PointEntity entity = getGridPoint(actVect);
                    if (entity.equals(PointEntity.MOVEABLE)) {
                        allList.add(actVect);
                    }
                }
            }
        }
        return allList;
    }

    @Deprecated
    public Set<Vector3i> getMoveableVectors2(Vector3i from, Vector3i to) {
        Set<Vector3i> allList = new HashSet<Vector3i>();
        for (Iterator<AbstractPointContainer> it = containers.iterator(); it.hasNext();) {
            AbstractPointContainer abstractPointContainer = it.next();
            Set<Vector3i> list = abstractPointContainer.getPointsSection(from, to);
            if (list != null) {
                allList.addAll(list);
            }
        }
        return allList;
    }
}
